#include "channels.h"
#include "users.h"
#include "extern.h"
#include "net.h"
#include "str.h"


int chan_init_hashtable (void)
{
	channelstb = HashTable_New (ServerConf.MaxChannels);
	if (channelstb == NULL)
		return -1;

	HashTable_SetMethods (channelstb, chan_compare, chan_gethash);
	return 0;
}

int chan_compare (void* E1, void* E2)
{
	Channel* channel = E1;
	const char*	key = E2;

	return (Strncmp (channel->name, key));
}

int chan_gethash (HashTable* htb, void* element)
{
	Channel *channel = element;
	return (hash_string (channel->name, htb->size));
}

Channel* chan_new (char name[CHAN_MAXNAMESIZE], char topic[CHAN_MAXTOPICSIZE], uchar modes, ulong owner)
{
 Channel *channel = malloc (sizeof (*channel));

	if (channel != NULL)
	{
		strncpy (channel->name, name, CHAN_MAXNAMESIZE);
		strncpy (channel->topic, topic, CHAN_MAXTOPICSIZE);
		channel->modes = modes;
		channel->owner = owner;
		channel->id = hash_string (channel->name, channelstb->size);
		channel->clients = List_New();
		if (channel->clients == NULL){
			free (channel);
			channel = NULL;
		}
		else
		{
			channel->blacklist = List_New();
			if (channel->blacklist == NULL)
			{
				free (channel->clients);
				free (channel);
				channel = NULL;
			}
		}
	}

 return (channel);
}

void chan_add (Channel *chan){
	HashTable_Insert (channelstb, chan, chan->name);
}

void chan_del (const char* channel)
{
	HashTable_Remove (channelstb, channel);
}

void chan_member_add (Channel* channel, const char* user, int level)
{
	ChannelClient* chclient = malloc (sizeof (*chclient));

	if (chclient != NULL)
	{
		strncpy (chclient->user, user, sizeof (chclient->user));
		chclient->level = level;
		List_PushTail (channel->clients, chclient);
	}
}

void chan_member_del (Channel* channel, const char* user)
{
	ChannelClient *chclient = NULL;

	LIST_FOREACH (chclient, channel->clients){
		if (strncmp (chclient->user, user, sizeof (chclient->user)) == 0){
			List_Del (channel->clients, &channel->clients->iter);
			break;
		}
	}
}

ChannelClient* chan_member_find (Channel *chan, const char* user)
{
	ChannelClient* client = NULL;

	LIST_FOREACH (client, chan->clients){
		if (strncmp (client->user, user, sizeof (client->user)) == 0)
			break;
	}
	return (client);
}

void chan_ban_add (Channel* chan, BlackList* banme)
{
	BlackList* blist = malloc (sizeof (*blist));

	if (blist != NULL)
	{
		strncpy (blist->nick, banme->nick, sizeof (blist->nick));
		strncpy (blist->user, banme->user, sizeof (blist->user));
		strncpy (blist->host, banme->host, sizeof (blist->host));
		List_PushTail (chan->blacklist, blist);
	}
}

void chan_ban_del (Channel* chan, const char* user)
{
	BlackList *blist = NULL;

	LIST_FOREACH (blist, chan->blacklist){
		if (strncmp (blist->user, user, sizeof (blist->user)) == 0){
			List_Del (chan->blacklist, &chan->blacklist->iter);
			break;
		}
	}
}

BlackList* chan_ban_find (Channel *chan, const char* user)
{
	BlackList* blist = NULL;

	LIST_FOREACH (blist, chan->blacklist){
		if (strncmp (blist->user, user, sizeof (blist->user)) == 0)
			break;
	}
	return (blist);
}
